﻿using Nop.Admin.Controllers;
using Nop.Admin.Extensions;
using Nop.Core.Domain.Messages;
using Nop.Plugin.Misc.MessageDesigner.Domain;
using Nop.Plugin.Misc.MessageDesigner.Models;
using Nop.Plugin.Misc.MessageDesigner.Services;
using Nop.Services.Localization;
using Nop.Services.Messages;
using Nop.Services.Security;
using Nop.Services.Stores;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Kendoui;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Plugin.Misc.MessageDesigner.Controllers
{
    public class MiscMessageDesignerController : BaseAdminController
    {
       #region Fields

        private readonly IMessageDesignerService _messageDesignerService;
        private readonly ILanguageService _languageService;
        private readonly ILocalizedEntityService _localizedEntityService;
        private readonly ILocalizationService _localizationService;
        private readonly IPermissionService _permissionService;
        private readonly IStoreService _storeService;
        private readonly IStoreMappingService _storeMappingService;
        private readonly IMessageTemplateService _messageTemplateService;

        #endregion Fields

        #region Constructors

        public MiscMessageDesignerController(IMessageDesignerService messageDesignerService, 
            ILanguageService languageService, 
            ILocalizedEntityService localizedEntityService,
            ILocalizationService localizationService,  
            IPermissionService permissionService, IStoreService storeService,
            IStoreMappingService storeMappingService, IMessageTemplateService messageTemplateService)
        {
            this._messageDesignerService = messageDesignerService;
            this._languageService = languageService;
            this._localizedEntityService = localizedEntityService;
            this._localizationService = localizationService;
            this._permissionService = permissionService;
            this._storeService = storeService;
            this._storeMappingService = storeMappingService;
            this._messageTemplateService = messageTemplateService;
        }

        public int GetTemplateId()
        {
            if (ControllerContext == null)
            {
                ControllerContext context = new ControllerContext(System.Web.HttpContext.Current.Request.RequestContext, this);
                ControllerContext = context;
            }
            int templateId = Convert.ToInt32(ControllerContext.RequestContext.RouteData.Values["id"]);
            return templateId;
        }

        #endregion
        
        #region Utilities

        [NonAction]
        protected virtual void UpdateLocales(MessageDesign md, MessageDesignModel model)
        {
            foreach (var localized in model.Locales)
            {
                if(! string.IsNullOrEmpty(localized.Body))
                {
                    
                     DesignResultsModel designModel = _messageDesignerService.IsMessageDesignerId(localized.Body);
                     if (!designModel.IsSuccess)
                     {
                         localized.Body += "<div Id=\"messageDesignerName\" data-id=\"" + model.Id + "\"><!--Do Not DELETE THID DIV--></div>";
                     }
                }
               _localizedEntityService.SaveLocalizedValue(md,
                                                           x => x.Body,
                                                           localized.Body,
                                                           localized.LanguageId);
                
            }
        }

        [NonAction]
        protected virtual void PrepareStoresMappingModel(MessageDesignModel model, MessageDesign messageDesign, bool excludeProperties)
        {
            if (model == null)
                throw new ArgumentNullException("model");

            model.AvailableStores = _storeService
                .GetAllStores()
                .Select(s => s.ToModel())
                .ToList();
            if (!excludeProperties)
            {
                if (messageDesign != null)
                {
                    model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(messageDesign);
                }
            }
        }

        [NonAction]
        protected virtual void SaveStoreMappings(MessageDesign messageTemplate, MessageDesignModel model)
        {
            var existingStoreMappings = _storeMappingService.GetStoreMappings(messageTemplate);
            var allStores = _storeService.GetAllStores();
            foreach (var store in allStores)
            {
                if (model.SelectedStoreIds != null && model.SelectedStoreIds.Contains(store.Id))
                {
                    //new store
                    if (existingStoreMappings.Count(sm => sm.StoreId == store.Id) == 0)
                        _storeMappingService.InsertStoreMapping(messageTemplate, store.Id);
                }
                else
                {
                    //remove store
                    var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id);
                    if (storeMappingToDelete != null)
                        _storeMappingService.DeleteStoreMapping(storeMappingToDelete);
                }
            }
        }

        [NonAction]
        protected virtual void PrepareStoresMappingModel(MessageTemplateLocalModel model, MessageTemplate messageTemplate, bool excludeProperties)
        {
            if (model == null)
                throw new ArgumentNullException("model");

            model.AvailableStores = _storeService
                .GetAllStores()
                .Select(s => s.ToModel())
                .ToList();
            if (!excludeProperties)
            {
                if (messageTemplate != null)
                {
                    model.SelectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(messageTemplate);
                }
            }
        }

       
        #endregion
       
        #region Methods

        #region Designer
        public ActionResult Index()
        {
            return RedirectToAction("List");
        }

        public ActionResult List()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var model = new MessageTemplateListLocalModel();
            //stores
            model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });

            return View("~/Plugins/Misc.MessageDesigner/Views/List.cshtml", model);
        }

        [HttpPost]
        public ActionResult List(DataSourceRequest command, MessageTemplateListLocalModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageTemplates = _messageTemplateService.GetAllMessageTemplates(model.SearchStoreId);
            var gridModel = new DataSourceResult
            {
                Data = messageTemplates.Select(x =>
                {
                    var templateModel = new MessageTemplateLocalModel()
                    {
                        Id = x.Id,
                        Name = x.Name,
                        Subject = x.Subject,
                        IsActive = x.IsActive,
                        LimitedToStores = x.LimitedToStores,
                    };
                    var designResultsModel = _messageDesignerService.IsMessageDesignerId(x.Body);
                    if (designResultsModel.IsSuccess)
                    {
                        templateModel.DesignId = designResultsModel.IdValue;
                        templateModel.DesignName = _messageDesignerService.GetMessageDesignById(templateModel.DesignId).Name;
                        if (model.MessageDesignId == templateModel.DesignId)
                            templateModel.DesignName += "(Current)";
                    }
                    else
                    {
                        templateModel.DesignId = 0;
                        templateModel.DesignName = "";
                    }
                    PrepareStoresMappingModel(templateModel, x, false);
                    var stores = _storeService
                            .GetAllStores()
                            .Where(s => !x.LimitedToStores || templateModel.SelectedStoreIds.Contains(s.Id))
                            .ToList();
                    for (int i = 0; i < stores.Count; i++)
                    {
                        templateModel.ListOfStores += stores[i].Name;
                        if (i != stores.Count - 1)
                            templateModel.ListOfStores += ", ";
                    }

                    return templateModel;
                }),
                Total = messageTemplates.Count
            };

            return Json(gridModel);
        }

        public ActionResult ViewTemplate(int templateId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();
            var model = new MessageDesignModel() ;
            var messageTemplate = _messageTemplateService.GetMessageTemplateById(templateId );
            if (messageTemplate == null)
                model.Body = "Error displaying message template";
            else
                model.Body = messageTemplate.Body;
           
            return PartialView("~/Plugins/Misc.MessageDesigner/Views/ViewDesign.cshtml", model);
        }
        #endregion

        #region Tab Views

        public ActionResult AddTemplateTab(int templateId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var model = new MessageDesignListModel();
            model.TemplateId = templateId;
            var messageTemplate = _messageTemplateService.GetMessageTemplateById(templateId);
            DesignResultsModel designResultsModel = _messageDesignerService.IsMessageDesignerContent(messageTemplate.Body);
            if (designResultsModel.IsSuccess)
            {
                model.DesignId = designResultsModel.IdValue;
                model.DesignName = _messageDesignerService.GetMessageDesignById(model.DesignId).Name;
            }
            else
            {
                model.DesignId = 0;
                model.DesignName = "None";
            }
            //stores
            model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });

            return PartialView("~/Plugins/Misc.MessageDesigner/Views/MessageDesignerTab.cshtml", model);
        }

        public ActionResult ViewDesign(int designId, int templateId = 0)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();
            var replacedBody = "Template Content will be replaced here";
            var messageTemplate = _messageTemplateService.GetMessageTemplateById(templateId);
            if (messageTemplate != null)
                replacedBody = messageTemplate.Body;
            var messageDesign = _messageDesignerService.GetMessageDesignById(designId);
            if (messageDesign == null)
                return Content("Error: could not find design");

            var resultModel = new ResultsModel();
            resultModel = _messageDesignerService.MergeDesginTemplate(resultModel, "View Design", messageDesign.Body, replacedBody);

            var model = new MessageDesignModel()
            {
                Body = resultModel.MergedBody,
            };

            return PartialView("~/Plugins/Misc.MessageDesigner/Views/ViewDesign.cshtml", model);
        }

        public ActionResult SelectDesign(int templateId, int designId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();
            var messageDesign = _messageDesignerService.GetMessageDesignById(designId);
            var messageTemplate = _messageTemplateService.GetMessageTemplateById(templateId);
            if (messageDesign == null || messageTemplate == null)
                //No message template found with the specified id
                return RedirectToAction("List", "MessageTemplate");

            var resultsModel = new ResultsModel();
            resultsModel = _messageDesignerService.MergeMessageDesign(messageDesign, messageTemplate);
            foreach (var suc in resultsModel.Success)
                SuccessNotification(suc);
            foreach (var err in resultsModel.Errors)
                ErrorNotification(err);

            return RedirectToAction("Edit", "MessageTemplate", new { id = templateId });
        }

        public ActionResult RemoveDesign(int templateId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageTemplate = _messageTemplateService.GetMessageTemplateById(templateId);
            if (messageTemplate == null)
                //No message template found with the specified id
                return RedirectToAction("List", "MessageTemplate");

            var resultsModel = new ResultsModel();
            resultsModel = _messageDesignerService.RemoveMessageDesign(messageTemplate);
            foreach (var suc in resultsModel.Success)
                SuccessNotification(suc);
            foreach (var err in resultsModel.Errors)
                ErrorNotification(err);

            return RedirectToAction("Edit", "MessageTemplate", new { id = templateId });
        }

        #endregion

        #region DesignList Edit Create Delete

        public ActionResult DesignList()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var model = new MessageDesignListModel();
            //stores
            model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });

            return View("~/Plugins/Misc.MessageDesigner/Views/DesignList.cshtml", model);   
        }

        [HttpPost]
        public ActionResult DesignList(DataSourceRequest command, MessageDesignListModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageDesgns = _messageDesignerService.GetAllMessageDesigns(model.SearchStoreId);
            var gridModel = new DataSourceResult
            {
                Data = messageDesgns.Select(x =>
                {
                    var designModel = x.ToModel();
                    if (designModel.Id == model.DesignId)
                        designModel.Selected = true;
                    PrepareStoresMappingModel(designModel, x, false);
                    var stores = _storeService
                            .GetAllStores()
                            .Where(s => !x.LimitedToStores || designModel.SelectedStoreIds.Contains(s.Id))
                            .ToList();
                    for (int i = 0; i < stores.Count; i++)
                    {
                        designModel.ListOfStores += stores[i].Name;
                        if (i != stores.Count - 1)
                            designModel.ListOfStores += ", ";
                    }
                    return designModel;
                }).OrderByDescending(x=> x.Selected),
                Total = messageDesgns.Count
            };

            return Json(gridModel);
        }

        public ActionResult Create()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var model = new MessageDesignModel() 
            {
                IsCreate = true,
            };
            //locales
            AddLocales(_languageService, model.Locales);
            //Stores
            PrepareStoresMappingModel(model, null, false);

            return View("~/Plugins/Misc.MessageDesigner/Views/Create.cshtml", model); 
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Create(MessageDesignModel model, bool continueEditing)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();
            
            if (ModelState.IsValid)
            {
                var designresultModel = _messageDesignerService.IsMessageDesignerContent(model.Body);
                if (designresultModel.IsSuccess)
                {
                    var messageDesign = model.ToEntity();
                    _messageDesignerService.InsertMessageDesign(messageDesign);
                    //add design code 
                    messageDesign.Body += "<div Id=\"messageDesignerName\" data-id=\"" + messageDesign.Id  + "\"><!--Do Not DELETE THID DIV--></div>";
                    _messageDesignerService.UpdateMessageDesign(messageDesign);
                    //locales
                    model.Id = messageDesign.Id;
                    UpdateLocales(messageDesign, model);
                    //Stores
                    SaveStoreMappings(messageDesign, model);
                    SuccessNotification(_localizationService.GetResource("Plugins.Misc.MessageDesigner.Added"));
                    return continueEditing ? RedirectToAction("Edit", new { id = messageDesign.Id }) : RedirectToAction("DesignList");
                }
            }

            ErrorNotification("The replacing code does not exist.");
            ErrorNotification("Place the code in the design HTML (follow the instructions)");
            //If we got this far, something failed, redisplay form
            ViewBag.AllLanguages = _languageService.GetAllLanguages(true);
            //Stores
            PrepareStoresMappingModel(model, null, true);
            return View("~/Plugins/Misc.MessageDesigner/Views/Create.cshtml", model); 
        }

        public ActionResult Edit(int id)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageDesign = _messageDesignerService.GetMessageDesignById(id);
            if (messageDesign == null)
                //No message template found with the specified id
                return RedirectToAction("List");
            
            var model = messageDesign.ToModel();
            model.messageTemplateListLocalModel = new MessageTemplateListLocalModel();
            model.messageTemplateListLocalModel.MessageDesignId = model.Id;
            //stores
            model.messageTemplateListLocalModel.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.messageTemplateListLocalModel.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });
            model.messageTemplateListLocalModel.MessageDesignId = id;
            //Store
            PrepareStoresMappingModel(model, messageDesign, false);
            //locales
            AddLocales(_languageService, model.Locales, (locale, languageId) =>
            {
                locale.Body = messageDesign.GetLocalized(x => x.Body, languageId, false, false);
            });

            //ViewData["nop.RichEditor.EnableFullPage"] = true;
            return View("~/Plugins/Misc.MessageDesigner/Views/Edit.cshtml", model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        [FormValueRequired("save", "save-continue")]
        public ActionResult Edit(MessageDesignModel model, bool continueEditing)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageDesign = _messageDesignerService.GetMessageDesignById(model.Id);
            if (messageDesign == null)
                //No message template found with the specified id
                return RedirectToAction("DesignList");
            
            if (ModelState.IsValid)
            {
                var designresultModel = _messageDesignerService.IsMessageDesignerContent(model.Body);
                if (designresultModel.IsSuccess)
                {
                    messageDesign = model.ToEntity(messageDesign);
                    if(!_messageDesignerService.IsMessageDesignerId(model.Body).IsSuccess)
                        messageDesign.Body += "<div Id=\"messageDesignerName\" data-id=\"" + messageDesign.Id + "\"><!--Do Not DELETE THID DIV--></div>";
                    
                    _messageDesignerService.UpdateMessageDesign(messageDesign);
                    //Stores
                    SaveStoreMappings(messageDesign, model);
                    //locales
                    UpdateLocales(messageDesign, model);

                    SuccessNotification(_localizationService.GetResource("Plugins.Misc.MessageDesigner.Updated"));

                    if (continueEditing)
                    {
                        //selected tab
                        SaveSelectedTabIndex();
                        return RedirectToAction("Edit", messageDesign.Id);
                    }
                    return RedirectToAction("DesignList");
                }
            }
            ErrorNotification("The replacing code does not exist.");
            ErrorNotification("Place the code in the design HTML (follow the instructions)");
           //Store
            PrepareStoresMappingModel(model, messageDesign, true);
            return View("~/Plugins/Misc.MessageDesigner/Views/Edit.cshtml", model);
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageDesign = _messageDesignerService.GetMessageDesignById(id);
            if (messageDesign == null)
                //No message template found with the specified id
                return RedirectToAction("DesignList");

            _messageDesignerService.DeleteMessageDesign(messageDesign);

            SuccessNotification(_localizationService.GetResource("Plugins.Misc.MessageDesigner.Deleted"));
            return RedirectToAction("DesignList");
        }
        #endregion

        

        #region message templates

        public ActionResult TemplatesList(int  designId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var model = new MessageTemplateListLocalModel();
            model.MessageDesignId = designId;
            //stores
            model.AvailableStores.Add(new SelectListItem { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem { Text = s.Name, Value = s.Id.ToString() });

            return View("~/Plugins/Misc.MessageDesigner/Views/TemplatesList.cshtml", model);
        }

        [HttpPost]
        public ActionResult ListTemplates(DataSourceRequest command, MessageTemplateListLocalModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageTemplates = _messageTemplateService.GetAllMessageTemplates(model.SearchStoreId);
            var gridModel = new DataSourceResult
            {
                Data = messageTemplates.Select(x =>
                {
                    var templateModel = new MessageTemplateLocalModel() 
                    { 
                        Id = x.Id,
                        Name  = x.Name,
                        Subject = x.Subject,
                        IsActive = x.IsActive,
                        LimitedToStores =  x.LimitedToStores, 
                    };
                    var designResultsModel = _messageDesignerService.IsMessageDesignerId(x.Body);
                    if (designResultsModel.IsSuccess)
                    {
                        templateModel.DesignId = designResultsModel.IdValue;
                        templateModel.DesignName = _messageDesignerService.GetMessageDesignById(templateModel.DesignId).Name;
                        if (model.MessageDesignId == templateModel.DesignId)
                            templateModel.DesignName += "(Current)";
                    }
                    else
                    {
                        templateModel.DesignId = 0;
                        templateModel.DesignName = "";
                    }
                    PrepareStoresMappingModel(templateModel, x, false);
                    var stores = _storeService
                            .GetAllStores()
                            .Where(s => !x.LimitedToStores || templateModel.SelectedStoreIds.Contains(s.Id))
                            .ToList();
                    for (int i = 0; i < stores.Count; i++)
                    {
                        templateModel.ListOfStores += stores[i].Name;
                        if (i != stores.Count - 1)
                            templateModel.ListOfStores += ", ";
                    }
                        
                    return templateModel;
                }),
                Total = messageTemplates.Count
            };

            return Json(gridModel);
        }
        #endregion

        #region multi templates
       

        public ActionResult ApplyToSelected(string selectedIds, int designId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            var messageTemplates = new List<MessageTemplate>();
            if (selectedIds != null)
            {
                var ids = selectedIds
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => Convert.ToInt32(x))
                    .ToArray();
                messageTemplates.AddRange(_messageDesignerService.GetMessageTemplatesByIds(ids));
            }
            var messageDesign = _messageDesignerService.GetMessageDesignById(designId);
            foreach (var mt in messageTemplates)
            {
                
                var messageTemplate = _messageTemplateService.GetMessageTemplateById(mt.Id);
                if (messageDesign == null || messageTemplate == null)
                    //No message template found with the specified id
                    return RedirectToAction("List", "MessageTemplate");

                var resultsModel = new ResultsModel();
                resultsModel = _messageDesignerService.MergeMessageDesign(messageDesign, messageTemplate);
                foreach (var suc in resultsModel.Success)
                    SuccessNotification(mt.Name  + ": " +  suc);
                foreach (var err in resultsModel.Errors)
                    ErrorNotification(mt.Name + ": " +  err);
            }

            return RedirectToAction("Edit", "MiscMessageDesigner", new { id = designId });
        }

        public ActionResult RestoreNopTemplates()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageMessageTemplates))
                return AccessDeniedView();

            _messageDesignerService.ExecuteSQL("Restore.sql");
            SuccessNotification(_localizationService.GetResource("Nop templates has been restored"));
            return RedirectToAction("List");
        }

        #endregion

        #endregion

    }
}

